/*
 * Hierarchy.java
 * Created on October 4, 2007, 1:46 PM
 */
package org.osdtsystem.hierarchy;

import java.util.Collection;
import org.osdtsystem.options.CoverOptions;
import org.osdtsystem.dataset.Classification;
import org.osdtsystem.dataset.Dataset;
import org.osdtsystem.dataset.HierarchyView;
import java.util.Comparator;
import java.util.List;

/**
 * An interface for a hierarchy. A hierarchy may either be a simple one-dimensional
 * hierarchy which corresponds to a tree structure with bounded depth, or a complex
 * finite-dimensional hierarchy in which each dimension corresponds to a tree hierarchy.
 * @param <H> the type of the classes in the hierarchy
 * @author Martin Haulrich and Matthias Buch-Kromann
 */
public interface Hierarchy<H extends HClass> {
    /**
     * The number of dimensions in the hierarchy, where the simple hierarchy
     * associated with each dimension corresponds to a tree.
     * @return the dimensionality of the hierarchy
     */
    public int dimensions();

    /**
     * The top class in the hierarchy.
     * @return the top class in the hierarchy.
     */
    public H topClass();

    /**
     * The empty class in the hierarchy.
     * @return the empty class in the hierarchy.
     */
    public H emptyClass();

    /**
     * Is the class identical to the top class?
     * @param hclass the class
     * @return <code>true</code> if the class is the top class, <code>false</code>
     * otherwise.
     */
    public boolean isTop(H hclass);

    /**
     * Is the class identical to the empty class?
     * @param hclass the class
     * @return <code>true</code> if the class is the empty class, <code>false</code>
     * otherwise.
     */
    public boolean isEmpty(H hclass);

    /**
     * The list of direct subclasses of the given class. This operation does not
     * have to implemented, in which case the hierarchy should return
     * <code>null</code>.
     * @param hclass the hierarchy class
     * @return the list of direct subclasses, or <code>null</code>
     */
    // public H[] subclasses(H hclass);

    /**
     * The list of direct super classes of the given class. This operation
     * is a special case of superclasses(hclass, minDepth, maxDepth) with
     * minDepth = maxDepth = hclass.depth - 1.
     * @param hclass the class
     * @return the list of direct super classes
     */
    public Collection<H> superclasses(H hclass);

    /**
     * The list of super classes of a hierarchy that that are contained in the
     * root class, within the given range of depths. If minDepthBelowRoot
     * is zero, then the root class is included in this list.
     * @param hclass the hierarchy class
     * @param root the root class
     * @param minDepthBelowRoot the minimum depth below the root (inclusive)
     * @param maxDepthBelowRoot the maximum depth below the root (inclusive)
     * @return the list of all super classes of the class that are contained within contained in the root
     * class within the given depth range below the root
     */
    public Collection<H> superclassesBelowRoot(H hclass, H root,
                int minDepthBelowRoot, int maxDepthBelowRoot);

    /**
     * The list of super classes for a data point that fall within a given
     * root class, within the given range of depths. If minDepthBelowRoot
     * is zero, then the root class is included in this list.
     * @param view the view
     * @param dataset the dataset
     * @param identifier the identifier for the datapoint in the dataset
     * @param root the root class
     * @param minDepthBelowRoot the minimum depth below the root (inclusive)
     * @param maxDepthBelowRoot the maximum depth below the root (inclusive)
     * @return the list of all super classes of the class that are contained within contained in the root
     * class within the given depth range below the root
     */
    public Collection<H> superclassesBelowRoot(HierarchyView<H> view, Dataset dataset, int identifier, H root,
          int minDepthBelowRoot, int maxDepthBelowRoot);

    /**
     * Does hierarchy class <code>c1</code> contain <code>c2</code>?
     * Ie, are they identical or is <code>c2</code> a subclass of <code>c1</code>?
     * Returns <code>false</code> if the classes do not
     * belong to the hierarchy.
     * @param c1 the possible superclass
     * @param c2 the possible subclass
     * @return <code>true</code> if <code>c1</code> non-properly contains
     * <code>c2</code>, <code>false</code> otherwise.
     */
    public boolean contains(H c1, H c2);

    /**
     * Compute the intersection of a list of classes.
     * @param hclasses the classes in the intersection
     * @return the intersection of the classes
     */
    public H intersection(H... hclasses);

    /**
     * Compute the union of a list of classes.
     * @param hclasses the classes in the unreduced union
     * @return the classes in the reduced union (the empty array if the
     * union is empty)
     */
    public H[] union(H... hclasses);
    
    /**
     * Return a string representation of a given hierarchy class.
     * The class must belong to the hierarchy.
     * @param hclass the class
     * @return the string representation of the class
     */
    public String className(H hclass);

    /**
     * The terminal class corresponding to a data point in a view.
     * @param view the view
     * @param dataset the dataset
     * @param identifier the identifier for the data point
     * @return the terminal hierarchy class for the data point
     */
    public H dataClass(HierarchyView<H> view, Dataset dataset, int identifier);

    /**
     * The list of classes that contain the given data point. The classes must be
     * subclasses of <code>root</code> with the given maximal depth below the root class.
     * @param view the view
     * @param identifier the identifier for the data point
     * @param root the root class
     * @param maxDepthBelowRoot the maximal depth below the root
     * @return the list of classes that contain the data point within the given depth
     */
    // public H[] dataClasses(View<H> view, int identifier, H root, int maxDepthBelowRoot);

    /**
     * Does a hierarchy class contain a data point in a given view?
     * @param hclass the hierarchy class
     * @param view the view
     * @param dataset the dataset
     * @param identifier the identifier for the data point
     * @return <code>true</code> if the class contains the data point, <code>false</code>
     * otherwise.
     */
    public boolean contains(H hclass, HierarchyView<H> view, Dataset dataset, int identifier);

    /**
     * Comparator that can be used to sort hierarchy classes with respect to depth
     * (primary) and hash value (secondary).
     * @return a depth comparator
     */
    public Comparator<HClass> depthComparator();


    /**
     * The dimensions in a subclass that differ from a parent class. Ie, the list
     * of dimensions where the component class of the subclass is different from
     * the component class of the parent. The result is not well-defined if <code>
     * subclass</code> is not contained in <code>hclass</code>.
     * @param hclass the class
     * @param subclass the subclass
     * @param offset the dimension offset, ie, the number associated with the first
     * dimension in the hierarchy
     * @return the dimensions in which the two classes differ
     */
    public int[] subclassComponents(H hclass, H subclass, int offset);

    /**
     * The component class associated with a particular dimension of a given class.
     * @param hclass the class
     * @param dimension the dimension
     * @return the component class for the dimension
     * @throws IllegalArgumentException if the dimension is negative or &geq;
     * <code>dimensions()</code>
     */
    public HClass componentClass(H hclass, int dimension)
            throws IllegalArgumentException;

    /**
     * The component class associated with a particular dimension for a given data
     * point. The value returned by this method must equal the value returned by
     * <code>componentClass(dataClass(view, identifier), dimension)</code>, but
     * hierarchies are allowed to provide a more efficient implementation.
     * @param view the view
     * @param dataset the dataset
     * @param identifier the identifier for the data point
     * @param dimension the dimension
     * @return the component class for the data point in the given dimension
     * @throws IllegalArgumentException if the dimension is negative or &geq;
     * <code>dimensions()</code>
     */
    public HClass dataComponentClass(HierarchyView<H> view, Dataset dataset, int identifier, int dimension);

    /**
     * The component class at a given depth associated with a particular dimension of a given class.
     * The depth can be viewed informally as the maximal precision with which the component class
     * is specified.
     * @param hclass the class
     * @param dimension the dimension
     * @param depth the desired maximal depth
     * @return the component class for the dimension
     * @throws IllegalArgumentException if the dimension is negative or &geq;
     * <code>dimensions()</code>
     */
    public HClass componentClassAtDepth(H hclass, int dimension, int depth)
            throws IllegalArgumentException;

    /**
     * The component class at a given depth associated with a particular dimension for a given data
     * point. The value returned by this method must equal the component class returned by
     * <code>componentClassAtDepth(dataClass(view, identifier), dimension, depth)</code>, but
     * hierarchies are allowed to provide a more efficient implementation.
     * @param view the view
     * @param dataset the dataset
     * @param identifier the identifier for the data point
     * @param dimension the dimension
     * @param depth the depth of the component class
     * @return the component class at the given depth for the data point in the given dimension
     * @throws IllegalArgumentException if the dimension is negative or &geq;
     * <code>dimensions()</code>
     */
    public HClass dataComponentClassAtDepth(HierarchyView<H> view, Dataset dataset,
            int identifier, int dimension, int depth);

    /**
     * The canonical comparator for the hierarchy. This comparator should define
     * the "natural" ordering on the hierarchy, which is used for many of the
     * internal sorting operations of hierarchy classes.
     * @return the canonical comparator
     */
    // public Comparator<HClass> comparator();

    /**
     * The type of the classes in the hierarchy. This is used for reflection, eg,
     * when creating arrays with the correct type.
     * @return the class type
     */
    public Class<H> hclassType();

    /**
     * Return a hierarchy iterator that visits all classes in the hierarchy which
     * are (non-strictly) dominated by <code>root</code> and which (non-strictly)
     * dominate subclass. The maximal depth of visited classes relative to the root class
     * can be controlled from the iterator.
     * @param root the root class
     * @param subclass the subclass
     * @return the hierarchy iterator
     */
    public HierarchyIterator<H> hierarchyIterator(H root, H subclass);

    /**
     * Return a hierarchy iterator that visits all classes in the hierarchy which
     * are (non-strictly) dominated by <code>root</code> and which contain the
     * given data point. The maximal depth of visited classes relative to the root class
     * can be controlled from the iterator.
     * @param root the root class
     * @param view the view
     * @param dataset the dataset
     * @param identifier the identifier for the data point
     * @return the hierarchy iterator
     */
    public HierarchyIterator<H> hierarchyIterator(H root, HierarchyView<H> view, Dataset dataset, int identifier);

    /**
     * Classify the data points in a dataset below a given root.
     * @param view the view
     * @param dataset the dataset
     * @param root the root class
     * @return the classification
     */
    public Classification<H> classify(H root, HierarchyView<H> view, Dataset dataset);

    public CoverOptions classificationParameters();
}
